package com.proposition.paper.service.impl;

import com.proposition.commons.constant.ErrorCode;
import com.proposition.commons.constant.ExamCategory;
import com.proposition.commons.enums.PaperPattern;
import com.proposition.commons.model.ExamAcupointAdult;
import com.proposition.commons.model.ExamAnswer10;
import com.proposition.commons.model.StrategyTwo;
import com.proposition.exam.service.ExamAcupointAdultService;
import com.proposition.exam.service.ExamAnswer10Service;
import com.proposition.paper.service.AbstractPaperAddStrategy;
import com.proposition.paper.service.PaperAddStrategy;
import com.proposition.paper.service.PaperStrategyService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * 常规化组卷策略
 *
 * @author 杨凯
 * @create 2018-02-02 17:27
 **/
@Service("changguihua")
public class ChangGuiHuaServiceImpl extends AbstractPaperAddStrategy implements PaperAddStrategy {

	private static Logger logger = LoggerFactory.getLogger(ChangGuiHuaServiceImpl.class);

	@Autowired
	private PaperStrategyService paperStrategyService;

	@Autowired
	private ExamAcupointAdultService examAcupointAdultService;

	@Autowired
	private ExamAnswer10Service examAnswer10Service;

	@Override
	public int firstQuestion(String exam) {
		StrategyTwo strategyTwo = paperStrategyService.getStrategyTwo();
		String[] exams = examSplit(exam, ",");
		String examCategory = StringUtils.join(getExamCategory(exam), ",");
		String[] examCategoryArr = getExamCategory(exam);
		//第一题未按照组卷策略添加
		if (!strategyTwo.getExam1().equals(examCategory)) {
			return 2001;
		}
		//判断是否存在重复试题
		boolean flag = checkRepeat(exams);
		if (!flag) {
			//存在重复试题
			return 2002;
		}
		List<String> chengren = new ArrayList<>();
		List<String> erke = new ArrayList<>();
		for (int i = 0; i < examCategoryArr.length; i++) {
			//成人穴位
			if (examCategoryArr[i].equals(ExamCategory.CHENG_REN_XW)) {
				chengren.add(exams[i]);
			} else {
				erke.add(exams[i]);
			}
		}
		//成人穴位大于1才可以比对
		if (chengren.size() > 1) {
			return checkAcupointAdult(chengren);
		}

		//儿科穴位大于1才可以比对
		if (erke.size() > 1) {
			return checkAcupointPediatric(erke);
		}
		return ErrorCode.SUCCESS;
	}

	@Override
	public int secondQuestion(String exam) {
		StrategyTwo strategyTwo = paperStrategyService.getStrategyTwo();
		String[] exams = examSplit(exam, ",");
		String examCategory = StringUtils.join(getExamCategory(exam), ",");
		String[] examCategoryArr = getExamCategory(exam);
		//第二题未按照组卷策略添加
		if (!strategyTwo.getExam2().equals(examCategory)) {
			return 2007;
		}

		//检测试题重复性
		boolean flag = checkRepeat(exams);
		if (!flag) {
			//有重复试题
			return 2008;
		}
		//成人手法列表
		List<String> chengrensf = new ArrayList<>();
		//检测成人手法是否有重复大类
		for (int i = 0; i < examCategoryArr.length; i++) {
			if (examCategoryArr[i].equals(ExamCategory.CHENG_REN_SF)) {
				chengrensf.add(exams[i]);
			}
		}
		//检测成人穴位是否为同一大类
		if (chengrensf.size() > 1) {
			return checkTechnique(chengrensf);
		}

		return ErrorCode.SUCCESS;
	}

	@Override
	public int thirdQuestion(String exam) {
		//获取组卷策略
		StrategyTwo two = paperStrategyService.getStrategyTwo();
		String examCategory = exam.substring(0, 2);
		boolean flag = checkExamIsUse(PaperPattern.CHANG_GUI,3,exam);
		if(flag){
			return 2012;
		}
		int count;
		int categoryCount = selectUsedByPaperId(PaperPattern.CHANG_GUI, 3, examCategory);
		switch (examCategory) {
			//儿科整套手法
			case ExamCategory.ER_KE_ZT:
				//未按照组卷策略添加
				count = two.getExamEK();
				if (count == 0) {
					return 2010;
				}

				//如果数量相等 ,则该分类不能进行使用
				if (categoryCount >= two.getExamEK()) {
					return 2011;
				}
				break;
			//伤科整套手法
			case ExamCategory.SHANG_KE_ZT:
				count = two.getExamSK();
				if (count == 0) {
					return 2010;
				}
				//如果数量相等 ,则该分类不能进行使用
				if (categoryCount >= two.getExamSK()) {
					return 2011;
				}
				break;
			//妇科整套手法
			case ExamCategory.FU_KE_ZT:
				count = two.getExamFK();
				if (count == 0) {
					return 2010;
				}
				//如果数量相等 ,则该分类不能进行使用
				if (categoryCount >= two.getExamFK()) {
					return 2011;
				}
				break;
			//内科整套手法
			case ExamCategory.NEI_KE_ZT:
				count = two.getExamNK();
				if (count == 0) {
					return 2010;
				}
				//如果数量相等 ,则该分类不能进行使用
				if (categoryCount >= two.getExamNK()) {
					return 2011;
				}
				break;
			default:
				//未按照组卷策略添加
				return 2010;
		}
		return ErrorCode.SUCCESS;

	}

	/**
	 * 检测成人穴位部位和经络是否重复
	 *
	 * @param list
	 * @return
	 */
	public int checkAcupointAdult(List<String> list) {
		//获取试题列表
		List<Integer> partArr = new ArrayList<Integer>();
		List<String> meridianArr = new ArrayList<String>();
		for (String e : list) {
			//从成人穴位中查找，如果没有则返回NULL 代表人工组卷没有按照组卷策略添加
			ExamAcupointAdult examAcupointAdult = examAcupointAdultService.selectById(e);
			if (null == examAcupointAdult) {
				return 2001;
			}
			partArr.add(examAcupointAdult.getPartIdAdult());
			meridianArr.add(examAcupointAdult.getMeridianAdult());
		}
		//判断部位
		for (int i = 0; i < partArr.size() - 1; i++) {
			for (int j = i + 1; j < partArr.size(); j++) {
				//如果两个题部位顺序不一样或者相同部位则不正确
				if (Objects.equals(partArr.get(i), partArr.get(j))) {
					//部位顺序有问题
					return 2004;
				}
			}
		}
		//判断归经有没有重复
		for (int i = 0; i < meridianArr.size() - 1; i++) {
			for (int j = i + 1; j < meridianArr.size(); j++) {
				//不能为相同经络
				if (meridianArr.get(i).equals(meridianArr.get(j))) {
					return 2005;
				}
			}
		}
		return ErrorCode.SUCCESS;
	}


	/**
	 * 检测儿科穴位经络是否重复
	 *
	 * @param list
	 * @return
	 */
	public int checkAcupointPediatric(List<String> list) {
		List<String> meridianArr = new ArrayList<String>();
		for (String e : list) {
			//从成人穴位中查找，如果没有则返回NULL 代表人工组卷没有按照组卷策略添加
			ExamAcupointAdult examAcupointAdult = examAcupointAdultService.selectById(e);
			if (null == examAcupointAdult) {
				//没有按照组卷策略添加
				return 2001;
			}
			meridianArr.add(examAcupointAdult.getMeridianAdult());
		}
		//判断归经有没有重复
		for (int i = 0; i < meridianArr.size() - 1; i++) {
			for (int j = i + 1; j < meridianArr.size(); j++) {
				//不能为相同经络
				if (meridianArr.get(i).equals(meridianArr.get(j))) {
					return 2006;
				}
			}
		}
		return ErrorCode.SUCCESS;
	}

	/**
	 * 判断手法部位是否正确
	 *
	 * @param list
	 * @return
	 */
	public int checkTechnique(List<String> list) {
		List<Integer> techniqueId = new ArrayList<Integer>();

		for (String examId : list) {
			//从手法中查找该试题
			ExamAnswer10 examAnswer10 = examAnswer10Service.selectById(examId);
			if (null == examAnswer10) {
				logger.warn("手法查询对象为空");
				//没有按照组卷策略添加
				return 2007;
			}
			techniqueId.add(examAnswer10.getSinglePloyFiveCategoryId());
		}
		//判断类型有没有重复
		for (int i = 0; i < techniqueId.size() - 1; i++) {
			for (int j = i + 1; j < techniqueId.size(); j++) {
				if (techniqueId.get(i).equals(techniqueId.get(j))) {
					logger.warn("单项手法部位重复");
					return 2009;
				}
			}
		}
		return ErrorCode.SUCCESS;
	}


}
